<template>
  <div>
    <el-row :gutter="20" type="flex">
      <el-col :span="4">
        <el-input v-model.trim="attr.name" title="属性名" :class="{'validate-error': attr._error.name}" :disabled="attr._inherit === true" placeholder="属性名" @input="onChange" />
      </el-col>
      <el-col :span="4">
        <el-input v-model.trim="attr.field" title="属性标识" :class="{'validate-error': attr._error.field}" :disabled="attr._inherit === true" placeholder="属性标识" @input="onChange" />
      </el-col>
      <el-col :span="3">
        <el-select v-model="attr.dtype" title="数据类型" :class="{'validate-error': attr._error.dtype}" :disabled="attr._inherit === true" clearable class="filter-item" placeholder="数据类型" @change="onDataTypeSelected()" @visible-change="onDataTypeVisibleChange">
          <el-option v-for="item in availableDatatypes" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-col>
      <el-col :span="4">
        <number-input v-if="attr.dtype !== 'enum' && attr.dtype !== 'datasource' && attr.dtype !== 'foreign'" v-model.number="attr.len" :disabled="attr._inherit === true" title="长度" placeholder="长度" @input="onChange" />
        <el-select v-if="attr.dtype === 'enum'" v-model.trim="attr.dvalue" title="枚举值" class="filter-item" :disabled="attr._inherit === true" placeholder="枚举值" @change="onChange">
          <el-option v-for="en in attr.enums" :key="en.value" :label="en.label" :value="en.value" />
        </el-select>
        <datasource-select
          v-if="attr.dtype === 'datasource'"
          v-model.trim="attr.dvalue"
          :disabled="attr._inherit === true"
          :url="attr.datasource.url"
          :value-key="attr.datasource.valueKey"
          :label-key="attr.datasource.labelKey"
          :response-key="attr.datasource.responseKey"
          title="数据源"
          placeholder="数据源"
          @input="onChange"
        />
        <treeselect
          v-if="attr.dtype === 'foreign'"
          v-model="attr.dvalue"
          :append-to-body="true"
          :disabled="attr._inherit === true"
          :multiple="false"
          :options="availableSchemas"
          :load-options="treeLoadOptions"
          :disable-branch-nodes="true"
          id-key="code"
          label-key="name"
          placeholder="请选择外键"
          @input="onChange"
        />
      </el-col>
      <el-col :span="4">
        <auto-input v-model.trim="attr.dvalue" title="默认值" :data-type="attr.dtype" :disabled="attr._inherit === true" :options="attr.enums" placeholder="默认值" @input="onChange" />
      </el-col>
      <el-col :span="2">
        <el-checkbox v-model.trim="attr.notnullable" :disabled="attr._inherit === true" @change="onChange">不可空</el-checkbox>
      </el-col>
      <el-col :span="4">
        <el-button v-show="showBatchBtn" title="批量更新实例属性" type="primary" icon="el-icon-finished" circle @click="onBatchUpdateInsts" />
        <el-button v-show="attr._inherit !== true" type="danger" icon="el-icon-delete" circle @click="onDelete" />
      </el-col>
    </el-row>
    <FormDialog
      title="编辑枚举值"
      :drawer="true"
      :show="dialogEnumFormVisible"
      width="30%"
      @on-ok="onSaveEnums"
      @on-cancel="onCancelEnums"
    >
      <el-form ref="myenumform" :model="attr" label-width="10px" size="mini">
        <el-form-item v-for="kv in attr.enums" :key="kv.id" label="">
          <el-row :gutter="8" type="flex">
            <el-col :span="8">
              <el-input v-model.trim="kv.value" title="关键字" placeholder="关键字" />
            </el-col>
            <el-col :span="8">
              <el-input v-model.trim="kv.label" title="显示值" placeholder="显示值" />
            </el-col>
            <el-col :span="8">
              <el-button type="danger" icon="el-icon-delete" circle @click="onRemoveKv(kv)" />
            </el-col>
          </el-row>
        </el-form-item>
        <el-form-item>
          <el-button type="text" icon="el-icon-plus" @click="onAddKv">添加枚举项</el-button>
        </el-form-item>
      </el-form>
    </FormDialog>

    <FormDialog
      title="编辑关联项"
      :drawer="true"
      :show="dialogDatasourceFormVisible"
      width="40%"
      @on-ok="onSaveDatasource"
      @on-cancel="onCancelDatasource"
    >
      <el-form ref="mydatasourceform" :model="attr.datasource" label-width="120px" size="mini" class="attr-form">
        <el-form-item label="数据源地址" required>
          <el-input v-model.trim="attr.datasource.url" title="数据源地址" placeholder="数据源URL" />
        </el-form-item>
        <el-form-item label="原始数据识别字段">
          <el-input v-model.trim="attr.datasource.responseKey" title="原始数据识别字段" placeholder="默认: data" />
        </el-form-item>
        <el-form-item label="数据项识别字段">
          <el-input v-model.trim="attr.datasource.valueKey" title="数据项识别字段" placeholder="默认: value" />
        </el-form-item>
        <el-form-item label="数据项显示字段">
          <el-input v-model.trim="attr.datasource.labelKey" required title="数据项显示字段" placeholder="默认: label" />
        </el-form-item>
      </el-form>
    </FormDialog>

    <FormDialog
      title="批量更新实例属性"
      :drawer="false"
      :show="dialogBatchUpdateInstVisible"
      width="40%"
      @on-ok="onSubmitBatchUpdate"
      @on-cancel="onCancelBatchUpdate"
    >
      <el-form ref="batchUpdateForm" label-width="120px" :model="batchForm" :rules="batchFormRules" size="mini" class="attr-form">
        <el-form-item label="属性名">
          {{ attr.name }}
        </el-form-item>
        <el-form-item label="属性值" prop="value">
          <auto-input v-model.trim="batchForm.value" :data-type="attr.dtype" :options="attr.enums" placeholder="默认值" @input="onChange" />
        </el-form-item>
      </el-form>
    </FormDialog>
  </div>
</template>

<script>
import Vue from 'vue'
import { pureTree } from '@neu/cmdb-ui/api/schema'
import { list as bizdefList } from '@neu/cmdb-ui/api/bizdef'
import { createUniqueString, deepClone } from '@neu/biz-core/utils'
import FormDialog from '@neu/biz-core/components/FormDialog'

export default {
  name: 'DynamicAttrForm',
  components: {
    FormDialog
  },
  props: {
    pureTreeType: {
      type: String,
      default: 'schemas'
    },
    value: {
      type: Object,
      default: () => {
        return {
          _dirty: createUniqueString(),
          _error: { name: false, field: false, dtype: false },
          _inherit: false,
          name: '',
          field: '',
          dtype: '',
          len: 255,
          dvalue: '',
          notnullable: false,
          enums: [],
          datasource: {}
        }
      }
    },
    usedDatatypes: {
      type: Array,
      default: () => {
        return []
      }
    },
    showBatchBtn: {
      type: Boolean,
      default: false
    }
  },
  data() {
    const validateValue = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请输入属性值'))
      } else {
        callback()
      }
    }
    return {
      original: this.getInitValue(this.value),
      attr: this.getInitValue(this.value),
      dialogEnumFormVisible: false,
      dialogDatasourceFormVisible: false,
      availableSchemas: null, // 外键属性可用的模型
      dialogBatchUpdateInstVisible: false,
      batchForm: {
        value: ''
      },
      batchFormRules: {
        value: [{ required: true, trigger: 'blur', validator: validateValue }]
      }
    }
  },
  computed: {
    availableDatatypes: function() {
      if (this.usedDatatypes.length > 0) {
        return this.$store.state.cmdb.datatypes.filter(it => this.usedDatatypes.includes(it.value))
      }
      return this.$store.state.cmdb.datatypes
    }
  },
  watch: {
    value: {
      handler(new_value, old_value) {
        this.attr = this.getInitValue(new_value)
      },
      deep: true
    }
  },
  methods: {
    getInitValue(val) {
      const obj = Object.assign({
        _dirty: createUniqueString(),
        _error: { name: false, field: false, dtype: false },
        _inherit: false,
        name: '',
        field: '',
        dtype: '',
        len: 255,
        dvalue: '',
        notnullable: false,
        enums: [],
        datasource: {}
      }, val)

      return deepClone(obj)
    },
    // 属性的数据类型选择事件，枚举类型需要打开枚举编辑框
    onDataTypeSelected() {
      if (this.attr.dtype === 'enum') {
        if (!this.attr.enums) this.attr.enums = []
        this.dialogEnumFormVisible = true
      } else if (this.attr.dtype === 'datasource') {
        if (!this.attr.datasource) this.attr.datasource = {}
        this.dialogDatasourceFormVisible = true
      }
      this.$emit('input', this.attr)
    },
    onDataTypeVisibleChange(visible) {
      if (!visible) {
        if (this.attr.dtype === 'enum') {
          if (!this.attr.enums) this.attr.enums = []
          this.dialogEnumFormVisible = true
        } else if (this.attr.dtype === 'datasource') {
          if (!this.attr.datasource) this.attr.datasource = {}
          this.dialogDatasourceFormVisible = true
        }
      }
    },
    // 添加一个枚举项
    onAddKv() {
      if (!this.attr.enums.some(a => a.value === '')) {
        this.attr.enums.push({
          id: createUniqueString(),
          value: '',
          label: ''
        })
        this.$emit('input', this.attr)
      }
    },
    // 移除一个枚举项
    onRemoveKv(kv) {
      const idx = this.attr.enums.findIndex(it => it.id === kv.id)
      Vue.delete(this.attr.enums, idx)
      this.$emit('input', this.attr)
    },
    // 枚举项设置完成
    onSaveEnums() {
      const idx = this.attr.enums.findIndex(it => it.value === '')
      Vue.delete(this.attr.enums, idx)
      this.$emit('input', this.attr)
      this.dialogEnumFormVisible = false
    },
    // 关闭枚举编辑框
    onCancelEnums() {
      this.attr.dtype = this.original.dtype
      this.attr.enums = deepClone(this.original.enums)
      this.$emit('input', this.attr)
      this.dialogEnumFormVisible = false
    },
    // 关联项设置完成
    onSaveDatasource() {
      this.$emit('input', this.attr)
      this.dialogDatasourceFormVisible = false
    },
    // 关闭关联项编辑框
    onCancelDatasource() {
      this.attr.dtype = this.original.dtype
      this.attr.datasource = deepClone(this.original.datasource)
      this.$emit('input', this.attr)
      this.dialogDatasourceFormVisible = false
    },
    // 外键的数据类型，加载树形结构数据
    treeLoadOptions({ action }) {
      if (action === 'LOAD_ROOT_OPTIONS') {
        if (this.pureTreeType === 'bizdef') {
          return bizdefList().then(response => {
            const data = response.data
            const treeData = data.map(e => { return { name: e.name, code: e._id, children: [] } })
            this.availableSchemas = treeData
          })
        } else {
          return pureTree().then(response => {
            this.availableSchemas = response.data
          })
        }
      }
    },
    onChange() {
      this.$emit('input', this.attr)
    },
    onDelete() {
      this.$emit('delete', this.attr)
    },
    onBatchUpdateInsts() {
      this.batchForm.value = this.attr.dvalue
      this.dialogBatchUpdateInstVisible = true
    },
    onSubmitBatchUpdate() {
      this.$refs.batchUpdateForm.validate(valid => {
        if (valid) {
          this.$emit('batch-update', { field: this.attr.field, value: this.batchForm.value })
          this.dialogBatchUpdateInstVisible = false
        }
      })
    },
    onCancelBatchUpdate() {
      this.dialogBatchUpdateInstVisible = false
      this.batchForm.value = ''
    }

  }
}
</script>
